package com.ssy.lingxi.search.serviceImpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ssy.lingxi.common.constant.CommonConstant;
import com.ssy.lingxi.common.constant.Constants;
import com.ssy.lingxi.common.constant.manage.ShopTypeEnum;
import com.ssy.lingxi.common.constant.marketing.ActivityTypeEnum;
import com.ssy.lingxi.common.constant.product.PriceTypeEnum;
import com.ssy.lingxi.common.constant.product.UnitPriceStrategyApplyTypeEnum;
import com.ssy.lingxi.common.constant.tree.Node;
import com.ssy.lingxi.common.constant.tree.TreeUtils;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.common.utils.PinyinUtils;
import com.ssy.lingxi.component.redis.service.IRedisStringUtils;
import com.ssy.lingxi.marketing.api.feign.ActivityGoodsControllerFeign;
import com.ssy.lingxi.marketing.api.model.request.ProductTagReq;
import com.ssy.lingxi.marketing.api.model.response.ProductTagResp;
import com.ssy.lingxi.member.merchant.api.feign.inner.MemberLevelRightCreditControllerFeign;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.MemberFeignLevelDetailVO;
import com.ssy.lingxi.search.api.model.request.CommoditySearchRequest;
import com.ssy.lingxi.search.api.model.request.CustomerAttributeRequest;
import com.ssy.lingxi.search.api.model.request.CustomerAttributeValueRequest;
import com.ssy.lingxi.search.api.model.request.ShareCodeRequest;
import com.ssy.lingxi.search.api.model.response.*;
import com.ssy.lingxi.search.common.SortTypeEnum;
import com.ssy.lingxi.search.common.tree.BrandNode;
import com.ssy.lingxi.search.common.tree.CategoryNode;
import com.ssy.lingxi.search.entity.SimpleAttribute;
import com.ssy.lingxi.search.entity.SimpleAttributeValue;
import com.ssy.lingxi.search.entity.SimpleCustomerAttribute;
import com.ssy.lingxi.search.entity.SimpleCustomerAttributeValue;
import com.ssy.lingxi.search.entity.*;
import com.ssy.lingxi.search.entity.channel.ChannelCommodityMember;
import com.ssy.lingxi.search.model.response.CategoryBrandResponse;
import com.ssy.lingxi.search.model.response.CategoryCommodityResponse;
import com.ssy.lingxi.search.repository.CommodityRepository;
import com.ssy.lingxi.search.service.IBrowseRecordService;
import com.ssy.lingxi.search.service.ICommodityService;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.core.CountResponse;
import org.elasticsearch.common.document.DocumentField;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.Max;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.ScriptSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 商品实现类
 * @author jw.chen
 * @version 2.0.0
 * @date 2020/6/22
 */
@Service
public class CommodityServiceImpl implements ICommodityService {

    @Resource
    private CommodityRepository commodityRepository;

    @Resource
    private RestHighLevelClient restHighLevelClient;

    @Resource
    private IRedisStringUtils redisStringUtils;

    @Resource
    private IBrowseRecordService browseRecordService;

    @Resource
    private ActivityGoodsControllerFeign activityGoodsControllerFeign;

    @Resource
    private MemberLevelRightCreditControllerFeign memberLevelRightCreditControllerFeign;

    /**
     * 分页查询商品列表
     * @param searchRequest             请求参数
     * @param isHighlight               是否需要高亮显示
     * @param isScoreShop               是否是积分商城
     */
    @Override
    public PageData<CommoditySearchResponse> searchCommodityList(CommoditySearchRequest searchRequest, Boolean isHighlight, Boolean isScoreShop){
        //四舍五入，保留两位小数
        DecimalFormat decimalFormat = new DecimalFormat("#.00");
        //获取参数
        Long loginMemberId = searchRequest.getLoginMemberId();
        Long loginMemberRoleId = searchRequest.getLoginMemberRoleId();
        Long shopId = searchRequest.getShopId();
        Integer orderType = searchRequest.getOrderType();
        int current = searchRequest.getCurrent() - 1;
        int pageSize = searchRequest.getPageSize();

        //查询条件
        QueryBuilder query = this.getBoolQueryBuilder(searchRequest);
        //根据条件获取排序规则
        SortBuilder scriptSortBuilder = getScriptSortBuilder(orderType, loginMemberId, loginMemberRoleId, shopId);
        //查询
        PageData<Commodity> result = this.getHighlightList(query, current, pageSize, scriptSortBuilder, isHighlight);
        List<Commodity> data = result.getData();
        if(!CollectionUtils.isEmpty(data)){
            //查询登录用户的所有上级对应的会员等级
            Map<String, Integer> memberLevelMap = getMemberLevel(loginMemberId, loginMemberRoleId);
            //遍历查询到的商品列表
            List<CommoditySearchResponse> resultList = data.stream().map(commodity -> {
                CommoditySearchResponse commoditySearchResponse = BeanUtil.copyProperties(commodity, CommoditySearchResponse.class);
                //查询当前登录用户在对应供应商下的等级
                Integer memberLevel = memberLevelMap.get(commodity.getMemberId() + Constants.UNDERLINE_STR + commodity.getMemberRoleId());
                //根据价格策略设置价格
                this.setCommodityPrice(commodity, shopId, loginMemberId, loginMemberRoleId, memberLevel);
                //不同商城显示不同的已售数量
                List<CommoditySoldCount> commoditySoldCountList = commodity.getCommoditySoldCountList();
                if (commoditySoldCountList != null && commoditySoldCountList.size() > 0) {
                    commoditySoldCountList.forEach(commoditySoldCount -> {
                        Long commoditySoldCountShopId = commoditySoldCount.getShopId();
                        double sold = commoditySoldCount.getSold();
                        if (commoditySoldCountShopId.equals(shopId)) {
                            commoditySearchResponse.setSold(sold);
                        }
                    });
                }

                //根据是否登录设置库存
                if(loginMemberId != null && loginMemberId > 0){
                    //积分商城需要显示库存
                    if(isScoreShop){
                        this.getCommodityStock(commodity, loginMemberId, shopId);
                        double stockCount = commodity.getUnitPricePicList().stream().mapToDouble(CommodityUnitPricePic::getStockCount).sum();
                        commoditySearchResponse.setStockCount(Double.parseDouble(decimalFormat.format(stockCount)));
                    }
                }
                commoditySearchResponse.setPriceType(commodity.getPriceType());
                commoditySearchResponse.setMax(commodity.getMax());
                commoditySearchResponse.setMin(commodity.getMin());
                return commoditySearchResponse;
            }).collect(Collectors.toList());

            //积分商城不需要显示活动信息
            if(!isScoreShop){
                //获取商品相关的活动信息
                this.getActivityGoods(resultList, shopId, loginMemberId, loginMemberRoleId);
            }
            return new PageData<>(result.getTotalCount(), resultList);
        }else{
            return new PageData<>(0L, new ArrayList<>());
        }
    }

    /**
     * 查询登录用户的所有上级对应的会员等级
     */
    private Map<String, Integer> getMemberLevel(Long loginMemberId, Long loginMemberRoleId){
        Map<String, Integer> memberLevelMap = new HashMap<>();
        MemberFeignVO memberFeignVO = new MemberFeignVO();
        memberFeignVO.setMemberId(loginMemberId);
        memberFeignVO.setRoleId(loginMemberRoleId);
        Wrapper<List<MemberFeignLevelDetailVO>> subMemberLevels = memberLevelRightCreditControllerFeign.findSubMemberLevels(memberFeignVO);
        if(subMemberLevels != null && ResponseCode.SUCCESS.getCode() == subMemberLevels.getCode()){
            List<MemberFeignLevelDetailVO> data = subMemberLevels.getData();
            if(!CollectionUtils.isEmpty(data)){
                data.stream().filter(memberFeignLevelDetailVO -> memberFeignLevelDetailVO.getRelType() == 1).forEach(memberFeignLevelDetailVO -> {
                    Long upperMemberId = memberFeignLevelDetailVO.getUpperMemberId();
                    Long upperRoleId = memberFeignLevelDetailVO.getUpperRoleId();
                    Integer level = memberFeignLevelDetailVO.getLevel();
                    memberLevelMap.put(upperMemberId + Constants.UNDERLINE_STR + upperRoleId, level);
                });
            }
        }
        return memberLevelMap;
    }

    /**
     * 获取商品相关的活动信息
     * @param resultList
     * @param shopId
     * @param loginMemberId
     * @param loginMemberRoleId
     */
    private void getActivityGoods(List<CommoditySearchResponse> resultList, Long shopId, Long loginMemberId, Long loginMemberRoleId){
        //增加活动标签
        if (!CollectionUtils.isEmpty(resultList)) {
            // 活动内部接口请求
            ProductTagReq productTagReq = new ProductTagReq();
            productTagReq.setShopId(shopId);
            //判断是否已登录
            if(loginMemberId != null && loginMemberId > 0){
                productTagReq.setMemberId(loginMemberId);
                productTagReq.setRoleId(loginMemberRoleId);
            }

            //过滤不显示的活动类型
            List<Integer> filterActivityType = new ArrayList<>();
            filterActivityType.add(ActivityTypeEnum.GROUP_PURCHASE.getCode());
            filterActivityType.add(ActivityTypeEnum.SET_MEAL.getCode());
            productTagReq.setFilterActivityType(filterActivityType);

            Map<Long, ProductTagResp> productTagRespMap=new HashMap<>();
            List<Long> commodityList = resultList.stream().map(CommoditySearchResponse::getId).collect(Collectors.toList());
            productTagReq.setProductIds(commodityList);
            try {
                //获取商品信息
                Wrapper<List<ProductTagResp>> listWrapper = activityGoodsControllerFeign.listActivityGoodsProductTag(productTagReq);
                if (listWrapper != null && listWrapper.getCode() == ResponseCode.SUCCESS.getCode()) {
                    List<ProductTagResp> productTagRespList = listWrapper.getData();
                    productTagRespMap = productTagRespList.stream().collect(Collectors.toMap(ProductTagResp::getProductId, ProductTagResp -> ProductTagResp));
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            //设置活动信息
            for (CommoditySearchResponse response : resultList) {
                ProductTagResp productTagResp = productTagRespMap.get(response.getId());
                if (productTagResp!=null) {
                    response.setPreferentialPrice(productTagResp.getPreferentialPrice());
                    response.setTagList(productTagResp.getTagList());
                }
            }
        }
    }

    /**
     * 根据排序类型获取对应的排序规则
     * @param orderType                 排序类型
     * @param loginMemberId             当前登录会员id
     * @param loginMemberRoleId         当前登录会员角色id
     * @param shopId                    商城id
     */
    private SortBuilder getScriptSortBuilder(Integer orderType, Long loginMemberId, Long loginMemberRoleId, Long shopId){
        if(orderType != null && orderType > 0){
            if(orderType.equals(SortTypeEnum.PriceDown.getCode())){
                return this.getMemberPriceScriptSortBuilder(loginMemberId, loginMemberRoleId, shopId).order(SortOrder.DESC);
            }else if(orderType.equals(SortTypeEnum.PriceUp.getCode())){
                return this.getMemberPriceScriptSortBuilder(loginMemberId, loginMemberRoleId, shopId).order(SortOrder.ASC);
            }else if(orderType.equals(SortTypeEnum.SoldDown.getCode())){
                return this.getCommoditySoldScriptSortBuilder(shopId).order(SortOrder.DESC);
            }else if(orderType.equals(SortTypeEnum.CreditDown.getCode())){
                return SortBuilders.fieldSort("creditScore").order(SortOrder.DESC);
            }
        }
        // 默认按上架时间倒序
        return SortBuilders.scoreSort().order(SortOrder.DESC).order(SortBuilders.fieldSort("publishTime").order(SortOrder.DESC).order());
    }

    /**
     * 高亮显示关键字
     * @param query         查询条件
     * @param current       当前页码
     * @param pageSize      每页显示条数
     */
    private PageData<Commodity> getHighlightList(QueryBuilder query, int current, int pageSize, SortBuilder sortBuilder, Boolean isHighlight){
        PageData<Commodity> commodity = new PageData<>();
        try{
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().trackTotalHits(true);
            sourceBuilder.query(query);
            //分页获取记录数，默认10
            sourceBuilder.from(current * pageSize);
            sourceBuilder.size(pageSize);
            //排序
            sourceBuilder.sort(sortBuilder);

            //是否需要高亮
            if(isHighlight){
                HighlightBuilder highlightBuilder = new HighlightBuilder();
                HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("name");  //为name字段创建字段高光色。
                highlightBuilder.field(highlightTitle);
                highlightBuilder.preTags("<span class='highlight'>");
                highlightBuilder.postTags("</span>");
                sourceBuilder.highlighter(highlightBuilder);
            }

            SearchRequest searchRequest = new SearchRequest(Constants.ES_COMMODITY_INDEX);
            searchRequest.source(sourceBuilder);
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            //是否需要高亮
            if(isHighlight){
                //遍历结果
                for(SearchHit hit : response.getHits()){
                    Map<String, Object> source = hit.getSourceAsMap();
                    //处理高亮片段
                    Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                    HighlightField nameField = highlightFields.get("name");
                    if(nameField != null){
                        Text[] fragments = nameField.fragments();
                        StringBuilder nameTmp = new StringBuilder();
                        for(Text text : fragments){
                            nameTmp.append(text);
                        }
                        //将高亮片段组装到结果中去
                        source.put("name", nameTmp.toString());
                    }
                }
            }

            long total = response.getHits().getTotalHits().value;
            SearchHits hits = response.getHits();
            SearchHit[] searchHits = hits.getHits();
            List<Commodity> commodityList = Arrays.stream(searchHits).map(searchHit -> new JSONObject(searchHit.getSourceAsMap()).toBean(Commodity.class)).collect(Collectors.toList());
            commodity.setTotalCount(total);
            commodity.setData(commodityList);
        }catch (Exception e){
            e.printStackTrace();
        }
        return commodity;
    }

    /**
     * 1：如果商城设置了价格策略，会员没有设置价格策略，以商城设置的为准
     * 2：如果商城设置了价格策略，会员也设置价格策略，以会员设置的为准
     * @param commodity
     * @param shopId
     * @param loginMemberId
     * @param loginMemberRoleId
     */
    @Override
    public void setCommodityPrice(Commodity commodity, Long shopId, Long loginMemberId, Long loginMemberRoleId, Integer loginMemberLevel){
        List<UnitPriceStrategy> unitPriceStrategyList = commodity.getUnitPriceStrategyList();
        List<UnitPriceStrategy> shopPriceStrategy = unitPriceStrategyList.stream().filter(unitPriceStrategy -> unitPriceStrategy.getShopId().equals(shopId) && unitPriceStrategy.getIsEnable() && !unitPriceStrategy.getIsMember()).collect(Collectors.toList());
        List<UnitPriceStrategy> memberPriceStrategy = unitPriceStrategyList.stream().filter(unitPriceStrategy -> unitPriceStrategy.getShopId().equals(shopId) && unitPriceStrategy.getIsEnable() && unitPriceStrategy.getIsMember()).collect(Collectors.toList());
        //判断是否登录
        if(loginMemberId != null && loginMemberId > 0){
            boolean flag = true;
            for(UnitPriceStrategy unitPriceStrategy : memberPriceStrategy){
                Integer applyType = unitPriceStrategy.getApplyType();
                if(UnitPriceStrategyApplyTypeEnum.Member.getCode().equals(applyType)){
                    //根据价格策略的会员来设置价格
                    CommodityMember commodityMember = new CommodityMember();
                    commodityMember.setMemberId(loginMemberId);
                    commodityMember.setMemberRoleId(loginMemberRoleId);
                    Set<CommodityMember> commodityMemberList = unitPriceStrategy.getCommodityMemberList();
                    if(commodityMemberList != null && commodityMemberList.contains(commodityMember)) {
                        this.setPriceStrategy(unitPriceStrategy, commodity);
                        flag = false;
                    }
                }else{
                    //根据价格策略的会员等级来设置价格
                    UnitPriceStrategyMemberLevel commodityMemberLevel = new UnitPriceStrategyMemberLevel();
                    commodityMemberLevel.setLevel(loginMemberLevel);
                    commodityMemberLevel.setMemberRoleId(loginMemberRoleId);
                    Set<UnitPriceStrategyMemberLevel> commodityMemberLevelList = unitPriceStrategy.getCommodityMemberLevelList();
                    if(commodityMemberLevelList != null && commodityMemberLevelList.contains(commodityMemberLevel)) {
                        this.setPriceStrategy(unitPriceStrategy, commodity);
                        flag = false;
                    }
                }
            }
            if(flag){
                //根据价格策略的商城来设置价格
                shopPriceStrategy.forEach(unitPriceStrategy -> this.setPriceStrategy(unitPriceStrategy, commodity));
            }
        }else{
            //根据价格策略的商城来设置价格
            shopPriceStrategy.forEach(unitPriceStrategy -> this.setPriceStrategy(unitPriceStrategy, commodity));
        }
    }

    /**
     * 根据价格策略来设置价格
     * @param unitPriceStrategy
     * @param commodity
     */
    private void setPriceStrategy(UnitPriceStrategy unitPriceStrategy, Commodity commodity){
        List<UnitPriceStrategyMember> memberUnitPriceList = unitPriceStrategy.getMemberUnitPriceList();
        List<CommodityUnitPricePic> unitPricePicList = commodity.getUnitPricePicList();
        unitPricePicList.forEach(unitPricePic -> {
            Long unitPricePicId = unitPricePic.getId();
            memberUnitPriceList.forEach(memberUnitPrice -> {
                SimpleId commodityUnitPriceAndPic = memberUnitPrice.getCommodityUnitPrice();
                Long commodityUnitPriceAndPicId = commodityUnitPriceAndPic.getId();
                if(unitPricePicId.equals(commodityUnitPriceAndPicId)){
                    Integer priceType = unitPriceStrategy.getPriceType();
                    Double max = unitPriceStrategy.getMax();
                    Double min = unitPriceStrategy.getMin();
                    commodity.setPriceType(priceType);
                    commodity.setMax(max);
                    commodity.setMin(min);
                    unitPricePic.setUnitPrice(memberUnitPrice.getUnitPrice());
                }
            });
        });
    }

    /**
     * 通过已售数量计算权重排序
     */
    private ScriptSortBuilder getCommoditySoldScriptSortBuilder(Long shopId){
        String inlineScript = "def commoditySoldCountList = params._source.commoditySoldCountList;" +
                "       double score = 0;" +
                "       if(commoditySoldCountList != null){" +
                "           for (int i = 0; i < commoditySoldCountList.length; i++) {" +
                "               def commoditySoldCountShopId = commoditySoldCountList[i].shopId;" +
                "               def commoditySoldCountSold= commoditySoldCountList[i].sold;" +
                "               if(commoditySoldCountShopId == " + shopId + "){" +
                "                   score = commoditySoldCountSold;" +
                "               }" +
                "           }" +
                "       }" +
                "       return score;";
        return SortBuilders.scriptSort(new Script(inlineScript), ScriptSortBuilder.ScriptSortType.NUMBER);
    }

    /**
     * 通过价格策略计算权重排序
     */
    private ScriptSortBuilder getMemberPriceScriptSortBuilder(Long loginMemberId, Long loginMemberRoleId, Long shopId){
        String inlineScript = "if (params._source.isUnitPriceStrategy == true) {" +
                "   def unitPriceStrategy = params._source.unitPriceStrategyList;" +
                "   double score = params._source.min;" +
                "   boolean isMemberPrice = true;" +
                "   for (int i = 0; i < unitPriceStrategy.length; i++) {" +
                "       if(unitPriceStrategy[i].isEnable == true && unitPriceStrategy[i].shopId == " + shopId + " && unitPriceStrategy[i].isMember != null && unitPriceStrategy[i].isMember) {" +
                "           def member = unitPriceStrategy[i].commodityMemberList;" +
                "           if(member != null){" +
                "               for(int j = 0; j < member.length; j++){" +
                "                   if(member[j].memberId == " + loginMemberId + " && member[j].memberRoleId == " + loginMemberRoleId + "){" +
                "                       if(unitPriceStrategy[i].priceType == " + PriceTypeEnum.Cash.getCode() + "){" +
                "                           score = unitPriceStrategy[i].min;" +
                "                       } else if(unitPriceStrategy[i].priceType == " + PriceTypeEnum.Consult.getCode() + "){" +
                "                           score = 0;" +
                "                       }" +
                "                       isMemberPrice = false;" +
                "                   }" +
                "               }" +
                "           }" +
                "      }" +
                "  }" +
                "  if(isMemberPrice){" +
                "       for (int i = 0; i < unitPriceStrategy.length; i++) {" +
                "           if(unitPriceStrategy[i].isEnable == true && unitPriceStrategy[i].shopId == " + shopId + " && unitPriceStrategy[i].isMember != null && !unitPriceStrategy[i].isMember) {" +
                "               if(unitPriceStrategy[i].priceType == " + PriceTypeEnum.Cash.getCode() + "){" +
                "                   score = unitPriceStrategy[i].min;" +
                "               } else if(unitPriceStrategy[i].priceType == " + PriceTypeEnum.Consult.getCode() + "){" +
                "                   score = 0;" +
                "               }" +
                "           }" +
                "       }" +
                "  }" +
                "  return score;" +
                "} else if(params._source.isUnitPriceStrategy == false && params._source.priceType == " + PriceTypeEnum.Consult.getCode() + ") {" +
                "   return 0;" +
                "} else {" +
                "   return params._source.min;" +
                "}";

        return SortBuilders.scriptSort(new Script(inlineScript), ScriptSortBuilder.ScriptSortType.NUMBER);
    }

    /**
     * 通过价格策略配置的产品定价筛选出对应的商品id
     */
    private List<Long> getMemberPriceTypeScriptQueryBuilder(Long loginMemberId, Long loginMemberRoleId, Long shopId, List<Integer> priceTypeList){
        String inlineScript = "if (params._source.isUnitPriceStrategy == true) {" +
                "   def unitPriceStrategy = params._source.unitPriceStrategyList;" +
                "   double priceType = params._source.priceType;" +
                "   boolean isMemberPrice = true;" +
                "   for (int i = 0; i < unitPriceStrategy.length; i++) {" +
                "       if(unitPriceStrategy[i].isEnable == true && unitPriceStrategy[i].shopId == " + shopId + " && unitPriceStrategy[i].isMember != null && unitPriceStrategy[i].isMember) {" +
                "           def member = unitPriceStrategy[i].commodityMemberList;" +
                "           if(member != null){" +
                "               for(int j = 0; j < member.length; j++){" +
                "                   if(member[j].memberId == " + loginMemberId + " && member[j].memberRoleId == " + loginMemberRoleId + "){" +
                "                       priceType = unitPriceStrategy[i].priceType;" +
                "                       isMemberPrice = false;" +
                "                   }" +
                "               }" +
                "           }" +
                "      }" +
                "  }" +
                "  if(isMemberPrice){" +
                "       for (int i = 0; i < unitPriceStrategy.length; i++) {" +
                "           if(unitPriceStrategy[i].isEnable == true && unitPriceStrategy[i].shopId == " + shopId + " && unitPriceStrategy[i].isMember != null && !unitPriceStrategy[i].isMember) {" +
                "               priceType = unitPriceStrategy[i].priceType;" +
                "           }" +
                "       }" +
                "  }";
                    for(Integer priceType : priceTypeList){
                        inlineScript = inlineScript +
                            "      if(priceType == " + priceType + "){" +
                            "          return params._source.id;" +
                            "      }";
                    }
                    inlineScript = inlineScript +
                "   return null;" +
                "} else {";
                    for(Integer priceType : priceTypeList){
                        inlineScript = inlineScript +
                            "      if(params._source.priceType == " + priceType + "){" +
                            "          return params._source.id;" +
                            "      }";
                    }
                    inlineScript = inlineScript +
                "   return null;" +
                "}";

        try{
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().trackTotalHits(true);
            sourceBuilder.scriptField("id" , new Script(inlineScript));

            // 通过CountRequest查询获得count
            CountRequest countRequest = new CountRequest();
            countRequest.indices(Constants.ES_COMMODITY_INDEX);
            CountResponse countResponse = restHighLevelClient.count(countRequest, RequestOptions.DEFAULT);
            sourceBuilder.size(Long.valueOf(countResponse.getCount()).intValue());

            SearchRequest searchRequest = new SearchRequest(Constants.ES_COMMODITY_INDEX);
            searchRequest.source(sourceBuilder);
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            SearchHits hits = response.getHits();
            SearchHit[] searchHits = hits.getHits();
            return Arrays.stream(searchHits).map(searchHit -> {
                DocumentField documentField = searchHit.getFields().get("id");
                Object value = documentField.getValue();
                if(value != null){
                    return Long.valueOf(String.valueOf(value));
                }
                return null;
            }).filter(Objects::nonNull).collect(Collectors.toList());
        }catch (Exception e){
            e.printStackTrace();
        }
        return new ArrayList<>();
    }

    /**
     * 通过价格策略筛选出对应的商品id
     */
    private List<Long> getMemberPriceScriptQueryBuilder(Long loginMemberId, Long loginMemberRoleId, Long shopId, Double max, Double min){
        String inlineScript = "if (params._source.isUnitPriceStrategy == true) {" +
                "   def unitPriceStrategy = params._source.unitPriceStrategyList;" +
                "   double score = params._source.min;" +
                "   boolean isMemberPrice = true;" +
                "   for (int i = 0; i < unitPriceStrategy.length; i++) {" +
                "       if(unitPriceStrategy[i].isEnable == true && unitPriceStrategy[i].shopId == " + shopId + " && unitPriceStrategy[i].isMember != null && unitPriceStrategy[i].isMember) {" +
                "           def member = unitPriceStrategy[i].commodityMemberList;" +
                "           if(member != null){" +
                "               for(int j = 0; j < member.length; j++){" +
                "                   if(member[j].memberId == " + loginMemberId + " && member[j].memberRoleId == " + loginMemberRoleId + "){" +
                "                       if(unitPriceStrategy[i].priceType == " + PriceTypeEnum.Cash.getCode() + "){" +
                "                           score = unitPriceStrategy[i].min;" +
                "                       } else if(unitPriceStrategy[i].priceType == " + PriceTypeEnum.Consult.getCode() + "){" +
                "                           score = 0;" +
                "                       }" +
                "                       isMemberPrice = false;" +
                "                   }" +
                "               }" +
                "           }" +
                "      }" +
                "  }" +
                "  if(isMemberPrice){" +
                "       for (int i = 0; i < unitPriceStrategy.length; i++) {" +
                "           if(unitPriceStrategy[i].isEnable == true && unitPriceStrategy[i].shopId == " + shopId + " && unitPriceStrategy[i].isMember != null && !unitPriceStrategy[i].isMember) {" +
                "               if(unitPriceStrategy[i].priceType == " + PriceTypeEnum.Cash.getCode() + "){" +
                "                   score = unitPriceStrategy[i].min;" +
                "               } else if(unitPriceStrategy[i].priceType == " + PriceTypeEnum.Consult.getCode() + "){" +
                "                   score = 0;" +
                "               }" +
                "           }" +
                "       }" +
                "  }";
                if(min != null && min > 0 && max != null && max > 0) {
                    inlineScript = inlineScript +
                            "      if(score >= " + min + " && score <= " + max + "){" +
                            "          return params._source.id;" +
                            "      }else{" +
                            "         return null;" +
                            "      }";
                }else {
                    if (min != null && min > 0) {
                        inlineScript = inlineScript +
                                "          if(score >= " + min + "){" +
                                "             return params._source.id;" +
                                "          }else{" +
                                "             return null;" +
                                "          }";
                    }
                    if (max != null && max > 0) {
                        inlineScript = inlineScript +
                                "          if(score <= " + max + "){" +
                                "              return params._source.id;" +
                                "          }else{" +
                                "              return null;" +
                                "          }";
                    }
                }
                inlineScript = inlineScript +
                "} else if(params._source.isUnitPriceStrategy == false && params._source.priceType == " + PriceTypeEnum.Consult.getCode() + ") {" +
                "   return null;" +
                "} else {";
                if(min != null && min > 0 && max != null && max > 0) {
                    inlineScript = inlineScript +
                            "      if(params._source.min >= " + min + " && params._source.min <= " + max + "){" +
                            "          return params._source.id;" +
                            "      }else{" +
                            "         return null;" +
                            "      }";
                }else {
                    if (min != null && min > 0) {
                        inlineScript = inlineScript +
                                "          if(params._source.min >= " + min + "){" +
                                "             return params._source.id;" +
                                "          }else{" +
                                "             return null;" +
                                "          }";
                    }
                    if (max != null && max > 0) {
                        inlineScript = inlineScript +
                                "          if(params._source.min <= " + max + "){" +
                                "              return params._source.id;" +
                                "          }else{" +
                                "              return null;" +
                                "          }";
                    }
                }
                inlineScript = inlineScript +
                "}";

        try{
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().trackTotalHits(true);
            sourceBuilder.scriptField("id" , new Script(inlineScript));

            // 通过CountRequest查询获得count
            CountRequest countRequest = new CountRequest();
            countRequest.indices(Constants.ES_COMMODITY_INDEX);
            CountResponse countResponse = restHighLevelClient.count(countRequest, RequestOptions.DEFAULT);
            sourceBuilder.size(Long.valueOf(countResponse.getCount()).intValue());

            SearchRequest searchRequest = new SearchRequest(Constants.ES_COMMODITY_INDEX);
            searchRequest.source(sourceBuilder);
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            SearchHits hits = response.getHits();
            SearchHit[] searchHits = hits.getHits();
            return Arrays.stream(searchHits).map(searchHit -> {
                DocumentField documentField = searchHit.getFields().get("id");
                Object value = documentField.getValue();
                if(value != null){
                    return Long.valueOf(String.valueOf(value));
                }
                return null;
            }).filter(Objects::nonNull).collect(Collectors.toList());
        }catch (Exception e){
            e.printStackTrace();
        }
        return new ArrayList<>();
    }

    /**
     * 构建查询条件
     * @param searchRequest 参数
     * @return
     */
    private BoolQueryBuilder getBoolQueryBuilder(CommoditySearchRequest searchRequest){
        // 查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        // 获取查询条件
        Long memberId = searchRequest.getMemberId();
        Long memberRoleId = searchRequest.getMemberRoleId();
        String memberName = searchRequest.getMemberName();
        String name = searchRequest.getName();
        Long brandId = searchRequest.getBrandId();
        List<Long> brandIdList = searchRequest.getBrandIdList();
        Long storeId = searchRequest.getStoreId();
        List<Long> storeIdList = searchRequest.getStoreIdList();
        String provinceCode = searchRequest.getProvinceCode();
        String cityCode = searchRequest.getCityCode();
        String regionCode = searchRequest.getRegionCode();
        Long categoryId = searchRequest.getCategoryId();
        List<Long> categoryIdList = searchRequest.getCategoryIdList();
        Long customerCategoryId = searchRequest.getCustomerCategoryId();
        List<Long> customerCategoryIdList = searchRequest.getCustomerCategoryIdList();
        List<CustomerAttributeRequest> customerAttributeList = searchRequest.getCustomerAttributeList();
        Double max = searchRequest.getMax();
        Double min = searchRequest.getMin();
        List<Integer> priceTypeList = searchRequest.getPriceTypeList();
        List<Long> idInList = searchRequest.getIdInList();
        List<Long> idNotInList = searchRequest.getIdNotInList();
        Long shopId = searchRequest.getShopId();
        Long loginMemberId = searchRequest.getLoginMemberId();
        Long loginMemberRoleId = searchRequest.getLoginMemberRoleId();
        Long publishStartTime = searchRequest.getPublishStartTime();
        Long publishEndTime = searchRequest.getPublishEndTime();
        List<Long> skuIdInList = searchRequest.getSkuIdInList();
        Integer carriageType = searchRequest.getCarriageType();

        // id搜索
        if(idInList != null && !idInList.isEmpty()){
            queryBuilder.must(QueryBuilders.termsQuery("id", idInList));
        }
        if(idNotInList != null && !idNotInList.isEmpty()){
            queryBuilder.mustNot(QueryBuilders.termsQuery("id", idNotInList));
        }

        // 拼接会员id搜索
        if(memberId != null && memberId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("memberId", memberId));
        }
        if(memberRoleId != null && memberRoleId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("memberRoleId", memberRoleId));
        }

        // 拼接店铺id搜索
        if(storeId != null && storeId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("storeId", storeId));
        }
        if(storeIdList != null && !storeIdList.isEmpty()){
            queryBuilder.must(QueryBuilders.termsQuery("storeId", storeIdList));
        }

        // 拼接会员名称搜索
        if(StringUtils.isNotEmpty(memberName)){
            queryBuilder.must(QueryBuilders.matchQuery("memberName", memberName));
        }

        // 拼接关键字搜索(商品名称)
        if(StringUtils.isNotEmpty(name)){
            queryBuilder.must(QueryBuilders.matchQuery("name", name));
        }

        // 拼接品牌搜索
        if(brandId != null && brandId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("brand.id", brandId));
        }
        if(brandIdList != null && !brandIdList.isEmpty()){
            queryBuilder.must(QueryBuilders.termsQuery("brand.id", brandIdList));
        }

        // 拼接城市搜索
        if(StringUtils.isNotEmpty(cityCode)){
            MatchQueryBuilder isAllArea = QueryBuilders.matchQuery("isAllArea", true);
            BoolQueryBuilder allCity = QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("commodityAreaList.provinceCode", provinceCode)).must(QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("commodityAreaList.isAllCity", false)).must(QueryBuilders.matchQuery("commodityAreaList.cityCode", cityCode)));
            BoolQueryBuilder city = QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("commodityAreaList.provinceCode", provinceCode)).must(QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("commodityAreaList.isAllCity", true)));
            BoolQueryBuilder should = QueryBuilders.boolQuery().should(allCity).should(city);
            NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery("commodityAreaList", should, ScoreMode.None);
            queryBuilder.must(QueryBuilders.boolQuery().should(isAllArea).should(nestedQueryBuilder));
        }else{
            // 拼接省份搜索
            if(StringUtils.isNotEmpty(provinceCode)){
                BoolQueryBuilder province = QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("isAllArea", false)).must(QueryBuilders.matchQuery("commodityAreaList.provinceCode", provinceCode));
                queryBuilder.must(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("isAllArea", true)).should(province));
            }
        }

        // 拼接平台后台分类搜索
        String attributeKey = null;
        String attributeValueKey = null;
        if(categoryId != null && categoryId > 0){
            String categoryKey = "customerCategory.category.fullId:*";
            queryBuilder.must(QueryBuilders.queryStringQuery(categoryKey + String.format(Constants.CATEGORY_FULL_ID_NUM, categoryId) + "*"));
            // 拼接属性搜索
            attributeKey = "unitPricePicList.attributeAndValueList.customerAttribute.attribute.id";
            attributeValueKey = "unitPricePicList.attributeAndValueList.customerAttributeValue.attributeValue.id";
        }
        if(categoryIdList != null && !categoryIdList.isEmpty()){
            categoryIdList.forEach(id -> {
                String categoryKey = "customerCategory.category.fullId:*";
                queryBuilder.must(QueryBuilders.queryStringQuery(categoryKey + String.format(Constants.CATEGORY_FULL_ID_NUM, id) + "*"));
            });
        }

        // 拼接会员分类搜索
        if(customerCategoryId != null && customerCategoryId > 0){
            String categoryKey = "customerCategory.fullId:*";
            queryBuilder.must(QueryBuilders.queryStringQuery(categoryKey + String.format(Constants.CATEGORY_FULL_ID_NUM, customerCategoryId) + "*"));
            // 拼接属性搜索
            attributeKey = "unitPricePicList.attributeAndValueList.customerAttribute.id";
            attributeValueKey = "unitPricePicList.attributeAndValueList.customerAttributeValue.id";
        }
        if(customerCategoryIdList != null && !customerCategoryIdList.isEmpty()){
            customerCategoryIdList.forEach(id -> {
                String categoryKey = "customerCategory.fullId:*";
                queryBuilder.must(QueryBuilders.queryStringQuery(categoryKey + String.format(Constants.CATEGORY_FULL_ID_NUM, id) + "*"));
            });
        }

        if(customerAttributeList != null && !customerAttributeList.isEmpty()){
            BoolQueryBuilder customerAttributeQueryBuilder = QueryBuilders.boolQuery();
            String finalAttributeKey = attributeKey;
            String finalAttributeValueKey = attributeValueKey;
            customerAttributeList.forEach(customerAttribute -> {
                Long customerAttributeId = customerAttribute.getCustomerAttributeId();
                List<CustomerAttributeValueRequest> customerAttributeValueList = customerAttribute.getCustomerAttributeValueList();
                customerAttributeValueList.forEach(customerAttributeValue -> {
                    Long customerAttributeValueId = customerAttributeValue.getId();
                    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
                    boolQueryBuilder.must(QueryBuilders.termQuery(finalAttributeKey, customerAttributeId));
                    boolQueryBuilder.must(QueryBuilders.termQuery(finalAttributeValueKey, customerAttributeValueId));
                    customerAttributeQueryBuilder.should(boolQueryBuilder);
                });
            });
            queryBuilder.must(customerAttributeQueryBuilder);
        }

        // 拼接定价方式搜索
        if(priceTypeList != null && !priceTypeList.isEmpty()){
            List<Long> commodityIdList = this.getMemberPriceTypeScriptQueryBuilder(loginMemberId, loginMemberRoleId, shopId, priceTypeList);
            queryBuilder.must(QueryBuilders.termsQuery("id", commodityIdList));
        }

        //上架时间
        if(publishStartTime != null && publishStartTime > 0){
            queryBuilder.must(QueryBuilders.rangeQuery("publishTime").gte(publishStartTime));
        }
        if(publishEndTime != null && publishEndTime > 0){
            queryBuilder.must(QueryBuilders.rangeQuery("publishTime").lte(publishEndTime));
        }

        //拼接价格搜索
        if((min != null && min > 0) || (max != null && max > 0)){
            List<Long> commodityIdList = this.getMemberPriceScriptQueryBuilder(loginMemberId, loginMemberRoleId, shopId, max, min);
            queryBuilder.must(QueryBuilders.termsQuery("id", commodityIdList));
        }

        //商城id
        if(shopId != null && shopId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("commodityShopList.shopId", shopId));
        }

        //商品skuId
        if(!CollectionUtils.isEmpty(skuIdInList)){
            queryBuilder.must(QueryBuilders.termsQuery("unitPricePicList.id", skuIdInList));
        }

        //运费方式
        if(carriageType != null && carriageType > 0){
            queryBuilder.must(QueryBuilders.matchQuery("logistics.carriageType", carriageType));
        }

        return queryBuilder;
    }

    /**
     * 查询商品列表(查全部，不分页)
     * @param commoditySearchRequest 参数
     */
    @Override
    public List<CommoditySearchResponse> queryCommodityList(CommoditySearchRequest commoditySearchRequest){
        Long shopId = commoditySearchRequest.getShopId();
        Long loginMemberId = commoditySearchRequest.getLoginMemberId();
        Long loginMemberRoleId = commoditySearchRequest.getLoginMemberRoleId();
        //查询商品信息
        List<Commodity> commodityList = this.getEsCommodityList(commoditySearchRequest);
        if(!CollectionUtils.isEmpty(commodityList)){
            //查询登录用户的所有上级对应的会员等级
            Map<String, Integer> memberLevelMap = this.getMemberLevel(loginMemberId, loginMemberRoleId);
            return commodityList.stream().map(commodity -> {
                //查询当前登录用户在对应供应商下的等级
                Integer loginMemberLevel = memberLevelMap.get(commodity.getMemberId() + Constants.UNDERLINE_STR + commodity.getMemberRoleId());
                //根据价格策略设置价格
                this.setCommodityPrice(commodity, shopId, loginMemberId, loginMemberRoleId, loginMemberLevel == null ? 0 : loginMemberLevel);
                //不同商城显示不同的已售数量
                CommoditySearchResponse commoditySearchResponse = BeanUtil.copyProperties(commodity, CommoditySearchResponse.class);
                List<CommoditySoldCount> commoditySoldCountList = commodity.getCommoditySoldCountList();
                if(commoditySoldCountList != null && commoditySoldCountList.size() > 0){
                    commoditySoldCountList.forEach(commoditySoldCount -> {
                        Long commoditySoldCountShopId = commoditySoldCount.getShopId();
                        double sold = commoditySoldCount.getSold();
                        if(commoditySoldCountShopId.equals(shopId)){
                            commoditySearchResponse.setSold(sold);
                        }
                    });
                }
                return commoditySearchResponse;
            }).collect(Collectors.toList());
        }else{
            return null;
        }
    }

    /**
     * 查询商品列表
     * @param commoditySearchRequest 参数
     */
    private List<Commodity> getEsCommodityList(CommoditySearchRequest commoditySearchRequest){
        Long shopId = commoditySearchRequest.getShopId();
        Integer orderType = commoditySearchRequest.getOrderType();
        Long loginMemberId = commoditySearchRequest.getLoginMemberId();
        Long loginMemberRoleId = commoditySearchRequest.getLoginMemberRoleId();

        //查询条件
        QueryBuilder query = this.getBoolQueryBuilder(commoditySearchRequest);
        //根据条件获取排序规则
        SortBuilder sortBuilder = getScriptSortBuilder(orderType, loginMemberId, loginMemberRoleId, shopId);
        //查询
        try{
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().trackTotalHits(true);
            sourceBuilder.query(query);
            // 通过CountRequest查询获得count
            CountRequest countRequest = new CountRequest();
            countRequest.indices(Constants.ES_COMMODITY_INDEX);
            CountResponse countResponse = restHighLevelClient.count(countRequest, RequestOptions.DEFAULT);
            sourceBuilder.size(Long.valueOf(countResponse.getCount()).intValue());
            //排序
            sourceBuilder.sort(sortBuilder);

            SearchRequest searchRequest = new SearchRequest(Constants.ES_COMMODITY_INDEX);
            searchRequest.source(sourceBuilder);
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            SearchHits hits = response.getHits();
            SearchHit[] searchHits = hits.getHits();
            return Arrays.stream(searchHits).map(searchHit -> new JSONObject(searchHit.getSourceAsMap()).toBean(Commodity.class)).collect(Collectors.toList());
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询商品详情
     * @param commodityId
     * @return
     */
    @Override
    public CommodityResponse getCommodityDetail(Long commodityId, Long shopId, UserLoginCacheDTO sysUser) {
        Long loginMemberId = null;
        Long loginMemberRoleId = null;
        int loginMemberLevel = 0;

        Commodity commodity = commodityRepository.findById(commodityId).orElse(null);
        if(commodity != null){
            if(sysUser != null){
                loginMemberId = sysUser.getMemberId();
                loginMemberRoleId = sysUser.getMemberRoleId();

                //查询当前登录用户的所有上级对应的会员等级
                MemberFeignVO memberFeignVO = new MemberFeignVO();
                memberFeignVO.setMemberId(loginMemberId);
                memberFeignVO.setRoleId(loginMemberRoleId);
                Wrapper<List<MemberFeignLevelDetailVO>> subMemberLevels = memberLevelRightCreditControllerFeign.findSubMemberLevels(memberFeignVO);
                if(subMemberLevels != null && ResponseCode.SUCCESS.getCode() == subMemberLevels.getCode()){
                    List<MemberFeignLevelDetailVO> data = subMemberLevels.getData();
                    if(!CollectionUtils.isEmpty(data)){
                        for(MemberFeignLevelDetailVO memberFeignLevelDetailVO : data){
                            if(memberFeignLevelDetailVO.getRelType() == 1 && commodity.getMemberId().equals(memberFeignLevelDetailVO.getUpperMemberId()) && commodity.getMemberRoleId().equals(memberFeignLevelDetailVO.getUpperRoleId())){
                                loginMemberLevel = memberFeignLevelDetailVO.getLevel();
                            }
                        }
                    }
                }

                //保存商品浏览记录--代客下单不用保存
                String company = sysUser.getCompany();
                if(StringUtils.isNotEmpty(company)){
                    browseRecordService.saveBrowseRecord(sysUser, shopId, commodityId);
                }
                //查询商品库存
                this.getCommodityStock(commodity, sysUser.getMemberId(), shopId);
            }
            //根据价格策略设置价格
            this.setCommodityPrice(commodity, shopId, loginMemberId, loginMemberRoleId, loginMemberLevel);
            //生成前端响应类
            CommodityResponse commodityResponse = BeanUtil.copyProperties(commodity, CommodityResponse.class);
            //不同的商城显示不同的已售数量
            List<CommoditySoldCount> commoditySoldCountList = commodity.getCommoditySoldCountList();
            if(commoditySoldCountList != null && commoditySoldCountList.size() > 0){
                commoditySoldCountList.forEach(commoditySoldCount -> {
                    Long commoditySoldCountShopId = commoditySoldCount.getShopId();
                    double sold = commoditySoldCount.getSold();
                    if(commoditySoldCountShopId.equals(shopId)){
                        commodityResponse.setSold(sold);
                    }
                });
            }

            //判断是否上架
            List<CommodityShop> commodityShopList = commodity.getCommodityShopList();
            if(!CollectionUtils.isEmpty(commodityShopList)){
                List<Long> commodityShopIdList = commodityShopList.stream().map(CommodityShop::getShopId).collect(Collectors.toList());
                if(commodityShopIdList.size() > 0 && commodityShopIdList.contains(shopId)){
                    commodityResponse.setIsPublish(true);
                }
            }
            return commodityResponse;
        }else{
            throw new BusinessException(ResponseCode.PRODUCT_COMMODITY_NOT_EXIST);
        }
    }

    /**
     * 通过商品skuId查询商品
     * @param commoditySkuId
     * @return
     */
    @Override
    public CommodityResponse getCommodityDetailBySkuId(Long commoditySkuId, Long shopId, UserLoginCacheDTO sysUser) {
        Long loginMemberId = null;
        Long loginMemberRoleId = null;
        int loginMemberLevel = 0;

        Commodity commodity = commodityRepository.findByUnitPricePicListId(commoditySkuId);
        if(commodity != null){
            if(sysUser != null){
                loginMemberId = sysUser.getMemberId();
                loginMemberRoleId = sysUser.getMemberRoleId();
                //查询当前登录用户的所有上级对应的会员等级
                MemberFeignVO memberFeignVO = new MemberFeignVO();
                memberFeignVO.setMemberId(loginMemberId);
                memberFeignVO.setRoleId(loginMemberRoleId);
                Wrapper<List<MemberFeignLevelDetailVO>> subMemberLevels = memberLevelRightCreditControllerFeign.findSubMemberLevels(memberFeignVO);
                if(subMemberLevels != null && ResponseCode.SUCCESS.getCode() == subMemberLevels.getCode()){
                    List<MemberFeignLevelDetailVO> data = subMemberLevels.getData();
                    if(!CollectionUtils.isEmpty(data)){
                        for(MemberFeignLevelDetailVO memberFeignLevelDetailVO : data){
                            if(memberFeignLevelDetailVO.getRelType() == 1 && commodity.getMemberId().equals(memberFeignLevelDetailVO.getUpperMemberId()) && commodity.getMemberRoleId().equals(memberFeignLevelDetailVO.getUpperRoleId())){
                                loginMemberLevel = memberFeignLevelDetailVO.getLevel();
                            }
                        }
                    }
                }
                //查询商品库存
                this.getCommodityStock(commodity, sysUser.getMemberId(), shopId);
            }
            //根据价格策略设置价格
            this.setCommodityPrice(commodity, shopId, loginMemberId, loginMemberRoleId, loginMemberLevel);
            //生成前端响应类
            CommodityResponse commodityResponse = BeanUtil.copyProperties(commodity, CommodityResponse.class);
            //判断是否上架
            List<CommodityShop> commodityShopList = commodity.getCommodityShopList();
            if(!CollectionUtils.isEmpty(commodityShopList)){
                List<Long> commodityShopIdList = commodityShopList.stream().map(CommodityShop::getShopId).collect(Collectors.toList());
                if(commodityShopIdList.size() > 0 && commodityShopIdList.contains(shopId)){
                    commodityResponse.setIsPublish(true);
                }
            }
            return commodityResponse;
        }else{
            throw new BusinessException(ResponseCode.PRODUCT_COMMODITY_NOT_EXIST);
        }
    }

    /**
     * 查询商品库存
     * @param commodity
     * @param memberId
     * @return
     */
    @Override
    public void getCommodityStock(Commodity commodity, Long memberId, Long shopId){
        if(commodity != null){
            DecimalFormat decimalFormat = new DecimalFormat("#.00");
            List<CommodityUnitPricePic> unitPricePicList = new ArrayList<>(commodity.getUnitPricePicList());
            if(!unitPricePicList.isEmpty()){
                //查询自己发布的商品
                if(memberId.longValue() == commodity.getMemberId().longValue()){
                    //组装redis键值格式
                    unitPricePicList.forEach(unitPriceAndPic -> {
                        String unitPriceAndPicId = CommonConstant.FREIGHT_SPACE_REDIS_KEY + shopId + "_" + unitPriceAndPic.getId();
                        Map<String, String> stringStringMap = redisStringUtils.hGetAll(unitPriceAndPicId, Constants.REDIS_PRODUCT_INDEX);
                        if(stringStringMap != null && stringStringMap.size() > 0){
                            Double stockCount = stringStringMap.values().stream().map(Double::parseDouble).reduce(Double::sum).get();
                            unitPriceAndPic.setStockCount(Double.parseDouble(decimalFormat.format(stockCount)));
                        }
                    });
                }else{
                    //组装redis键值格式
                    List<HashMap<String, String[]>> keyFieldList = unitPricePicList.stream().map(unitPriceAndPic -> {
                        HashMap<String, String[]> map = new HashMap<>();
                        String unitPriceAndPicId = CommonConstant.FREIGHT_SPACE_REDIS_KEY + shopId + "_" + unitPriceAndPic.getId();
                        String commodityMemberId = String.valueOf(memberId);
                        map.put(unitPriceAndPicId, new String[]{commodityMemberId, CommonConstant.FREIGHT_All});
                        return map;
                    }).collect(Collectors.toList());

                    //获取库存数据
                    List<Object> resultList = redisStringUtils.hMGetBatch(keyFieldList, Constants.REDIS_PRODUCT_INDEX);
                    for(int i = 0; i < unitPricePicList.size(); i++){
                        CommodityUnitPricePic unitPriceAndPic = unitPricePicList.get(i);
                        //计算当前商品的库存数
                        List<String> stockList = (List<String>)resultList.get(i);
                        if(stockList != null && !stockList.isEmpty()){
                            List<String> collect = stockList.stream().filter(StrUtil::isNotEmpty).collect(Collectors.toList());
                            if(!collect.isEmpty()){
                                Double stockCount = collect.stream().map(Double::parseDouble).reduce(Double::sum).get();
                                unitPriceAndPic.setStockCount(Double.parseDouble(decimalFormat.format(stockCount)));
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 查询商品分类树
     * @param memberId 会员id
     * @return
     */
    @Override
    public List<Node> getCategoryTree(Long shopId, Long memberId) {
        // 查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        //定义参数变量
        String esField;
        String redisKey;
        if(memberId != null && memberId > 0){
            esField = "customerCategory.fullId.keyword";
            redisKey = Constants.REDIS_KEY_CUSTOMER_CATEGORY;

            // 拼接会员id搜索
            queryBuilder.must(QueryBuilders.matchQuery("memberId", memberId));
        }else{
            esField = "customerCategory.category.fullId.keyword";
            redisKey = Constants.REDIS_KEY_CATEGORY;
        }

        // 按商城环境
        if(shopId != null && shopId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("commodityShopList.shopId", shopId));
        }

        //构建查询条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().trackTotalHits(true);
        SearchRequest search = new SearchRequest(Constants.ES_COMMODITY_INDEX);
        searchSourceBuilder.size(0);
        searchSourceBuilder.query(queryBuilder);
        //分组
        TermsAggregationBuilder aggregationCategoryId = AggregationBuilders.terms("group_categoryId").field(esField).size(1200000);
        searchSourceBuilder.aggregation(aggregationCategoryId);
        search.source(searchSourceBuilder);
        try{
            CategoryNode categoryNode = new CategoryNode();
            //搜索
            SearchResponse searchResponse = restHighLevelClient.search(search, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            if(aggregations != null){
                Terms brandTerms = aggregations.get("group_categoryId");
                List<? extends Terms.Bucket> brandBuckets = brandTerms.getBuckets();
                if(brandBuckets != null){
                    brandBuckets.forEach(bucket -> {
                        //将品类进行组装
                        String fullId = String.valueOf(bucket.getKey());
                        if(fullId.contains(Constants.SPLIT_STR_FULL_ID)){
                            String[] split = fullId.split(Constants.TRANSFER_STR + Constants.SPLIT_STR_FULL_ID);
                            if(split.length > 0){
                                for(int i = 0; i < split.length; i++){
                                    if(i == 0){
                                        //一级品类
                                        Set<Long> rootList = categoryNode.getRootList() == null ? new HashSet<>() : categoryNode.getRootList();
                                        rootList.add(Long.valueOf(split[i]));
                                        categoryNode.setRootList(rootList);
                                    }
                                    //所有品类
                                    Set<Long> sourceList = categoryNode.getSourceList() == null ? new HashSet<>() : categoryNode.getSourceList();
                                    sourceList.add(Long.valueOf(split[i]));
                                    categoryNode.setSourceList(sourceList);
                                }
                            }
                        }else{
                            //商品挂在一级品类下
                            Set<Long> rootList = categoryNode.getRootList() == null ? new HashSet<>() : categoryNode.getRootList();
                            rootList.add(Long.valueOf(fullId));
                            categoryNode.setRootList(rootList);
                            //所有品类
                            Set<Long> sourceList = categoryNode.getSourceList() == null ? new HashSet<>() : categoryNode.getSourceList();
                            sourceList.add(Long.valueOf(fullId));
                            categoryNode.setSourceList(sourceList);
                        }
                    });
                }
            }
            Map<String, String> categoryMap = redisStringUtils.hGetAll(redisKey, Constants.REDIS_PRODUCT_INDEX);
            Set<Long> rootCategoryIdList = categoryNode.getRootList();
            Set<Long> sourceCategoryIdList = categoryNode.getSourceList();
            //组装树结构
            if(rootCategoryIdList != null && !rootCategoryIdList.isEmpty()){
                List<Node> rootList = TreeUtils.getNodeList(rootCategoryIdList, categoryMap);
                List<Node> sourceList = TreeUtils.getNodeList(sourceCategoryIdList, categoryMap);
                return TreeUtils.buildTree(sourceList, rootList);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return new ArrayList<>();
    }

    /**
     * 查询商品属性
     * @param memberId
     * @param categoryId
     * @return
     */
    @Override
    public List<AttributeResponse> getAttributeByCategoryId(Long shopId, Long memberId, Long categoryId) {
        HashMap<Long, AttributeResponse> attributeMap = new HashMap<>();
        List<Commodity> commodityList;
        // 会员id
        if(memberId != null && memberId > 0){
            commodityList = commodityRepository.findByMemberIdAndCustomerCategoryIdAndCommodityShopListShopId(memberId, categoryId, shopId);
            //获取会员属性排序
        }else{
            commodityList = commodityRepository.findByCustomerCategoryCategoryIdAndCommodityShopListShopId(categoryId, shopId);
            //获取属性排序
        }
        commodityList.forEach(commodity -> commodity.getCommodityAttributeList().forEach(commodityAttribute -> {
            SimpleCustomerAttribute customerAttribute = commodityAttribute.getCustomerAttribute();
            if(customerAttribute != null){
                if(memberId != null && memberId > 0){
                    Long attributeId = customerAttribute.getId();
                    String attributeName = customerAttribute.getName();
                    //会员属性
                    Boolean isSearch = customerAttribute.getIsSearch();
                    if(isSearch){
                        List<SimpleCustomerAttributeValue> customerAttributeValueSet = commodityAttribute.getCustomerAttributeValueList();
                        customerAttributeValueSet.forEach(customerAttributeValue -> {
                            AttributeValueResponse attributeValueResponse = new AttributeValueResponse();
                            attributeValueResponse.setId(customerAttributeValue.getId());
                            attributeValueResponse.setValue(customerAttributeValue.getValue());

                            AttributeResponse attributeResponse = attributeMap.get(attributeId);
                            if(attributeResponse != null){
                                List<AttributeValueResponse> attributeValueList = attributeResponse.getAttributeValueList();
                                if(attributeValueList != null){
                                    if(!attributeValueList.contains(attributeValueResponse)){
                                        attributeValueList.add(attributeValueResponse);
                                    }
                                }else{
                                    attributeValueList = new ArrayList<>();
                                    attributeValueList.add(attributeValueResponse);
                                }
                            }else{
                                attributeResponse = new AttributeResponse();
                                attributeResponse.setId(attributeId);
                                attributeResponse.setName(attributeName);

                                List<AttributeValueResponse> attributeValueList = new ArrayList<>();
                                attributeValueList.add(attributeValueResponse);
                                attributeResponse.setAttributeValueList(attributeValueList);
                            }
                            attributeMap.put(attributeId, attributeResponse);
                        });
                    }
                }else{
                    //平台后台属性
                    SimpleAttribute attribute = customerAttribute.getAttribute();
                    if(attribute != null){
                        Long attributeId = attribute.getId();
                        String attributeName = attribute.getName();
                        Boolean isSearch = attribute.getIsSearch();
                        if(isSearch){
                            List<SimpleCustomerAttributeValue> customerAttributeValueSet = commodityAttribute.getCustomerAttributeValueList();
                            customerAttributeValueSet.forEach(customerAttributeValue -> {
                                SimpleAttributeValue attributeValue = customerAttributeValue.getAttributeValue();
                                if(attributeValue != null){
                                    AttributeValueResponse attributeValueResponse = new AttributeValueResponse();
                                    attributeValueResponse.setId(attributeValue.getId());
                                    attributeValueResponse.setValue(attributeValue.getValue());

                                    AttributeResponse attributeResponse = attributeMap.get(attributeId);
                                    if(attributeResponse != null){
                                        List<AttributeValueResponse> attributeValueList = attributeResponse.getAttributeValueList();
                                        if(attributeValueList != null){
                                            if(!attributeValueList.contains(attributeValueResponse)){
                                                attributeValueList.add(attributeValueResponse);
                                            }
                                        }else{
                                            attributeValueList = new ArrayList<>();
                                            attributeValueList.add(attributeValueResponse);
                                        }
                                    }else{
                                        attributeResponse = new AttributeResponse();
                                        attributeResponse.setId(attributeId);
                                        attributeResponse.setName(attributeName);

                                        List<AttributeValueResponse> attributeValueList = new ArrayList<>();
                                        attributeValueList.add(attributeValueResponse);
                                        attributeResponse.setAttributeValueList(attributeValueList);
                                    }
                                    attributeMap.put(attributeId, attributeResponse);
                                }
                            });
                        }
                    }
                }
            }
        }));
        return new ArrayList<>(attributeMap.values());
    }

    /**
     * 查询商品品牌
     * @return
     */
    @Override
    public List<BrandResponse> getBrand(Long shopId, Long memberId) {
        List<BrandResponse> brandList = new ArrayList<>();
        // 查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        // 拼接会员搜索
        if(memberId != null && memberId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("memberId", memberId));
        }
        // 按商城环境
        if(shopId != null && shopId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("commodityShopList.shopId", shopId));
        }
        //构建查询条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().trackTotalHits(true);
        SearchRequest search = new SearchRequest(Constants.ES_COMMODITY_INDEX);
        searchSourceBuilder.size(0);
        searchSourceBuilder.query(queryBuilder);
        //分组
        TermsAggregationBuilder aggregationBrandId = AggregationBuilders.terms("group_brandId").field("brand.id").size(1200000)
                .subAggregation(AggregationBuilders.terms("group_brandName").field("brand.name.keyword").subAggregation(AggregationBuilders.terms("group_brandLogoUrl").field("brand.logoUrl.keyword")));
        searchSourceBuilder.aggregation(aggregationBrandId);
        search.source(searchSourceBuilder);
        //搜索
        try{
            SearchResponse searchResponse = restHighLevelClient.search(search, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            if(aggregations != null){
                Terms brandTerms = aggregations.get("group_brandId");
                List<? extends Terms.Bucket> brandBuckets = brandTerms.getBuckets();
                if(brandBuckets != null){
                    brandBuckets.forEach(bucket -> {
                        Terms brandNameTerms = bucket.getAggregations().get("group_brandName");
                        List<? extends Terms.Bucket> brandNameBuckets = brandNameTerms.getBuckets();
                        if(brandNameBuckets != null){
                            brandNameBuckets.forEach(bucketName -> {
                                Terms brandLogoUrlTerms = bucketName.getAggregations().get("group_brandLogoUrl");
                                List<? extends Terms.Bucket> brandLogoUrlBuckets = brandLogoUrlTerms.getBuckets();
                                brandLogoUrlBuckets.forEach(bucketLogoUrl -> {
                                    BrandResponse brand = new BrandResponse();
                                    brand.setId(Long.valueOf(String.valueOf(bucket.getKey())));
                                    brand.setName(String.valueOf(bucketName.getKey()));
                                    brand.setLogoUrl(String.valueOf(bucketLogoUrl.getKey()));
                                    brandList.add(brand);
                                });
                            });
                        }
                    });
                }
            }
            return brandList;
        }catch (Exception e){
            return new ArrayList<>();
        }
    }

    /**
     * 查询商品品牌
     * @return
     */
    @Override
    public List<BrandNode> getPinyinSortBrand(Long shopId, Long memberId) {
        List<BrandResponse> brandResponseList = this.getBrand(shopId, memberId);
        if(brandResponseList != null && brandResponseList.size() > 0){
            //将品牌首字母拼音相同的合并
            Map<String, List<BrandResponse>> brandMap = new HashMap<>();
            brandResponseList.forEach(brandResponse -> {
                String brandName = brandResponse.getName();
                String firstChar = PinyinUtils.getFirstChar(brandName);
                //判断是否存在
                List<BrandResponse> brandList = brandMap.get(firstChar);
                if(brandList == null){
                    brandList = new ArrayList<>();
                }
                brandList.add(brandResponse);
                brandMap.put(firstChar, brandList);
            });
            //对map进行排序
            TreeMap<String, List<BrandResponse>> sort = MapUtil.sort(brandMap);
            //组装数据给前端
            List<BrandNode> brandNodeList = new ArrayList<>();
            for (Map.Entry<String, List<BrandResponse>> entry : sort.entrySet()) {
                String key = entry.getKey();
                List<BrandResponse> value = entry.getValue();
                //转成品牌节点
                BrandNode brandNode = new BrandNode();
                brandNode.setKey(key);
                brandNode.setTitle(key);
                brandNode.setItems(value);
                brandNodeList.add(brandNode);
            }
            return brandNodeList;
        }else{
            return null;
        }
    }

    /**
     * 查询商品最大价格/最大积分
     * @return
     */
    @Override
    public Double getCommodityMaxPrice(Long storeId) {
        //分组
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().trackTotalHits(true);
        AggregationBuilder builder = AggregationBuilders.max("maxPrice").field("max");
        searchSourceBuilder.aggregation(builder);
        //指定查找内容
        SearchRequest search = new SearchRequest(Constants.ES_COMMODITY_INDEX);
        if(storeId != null && storeId > 0){
            //构建查询条件
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            // 拼接会员搜索
            queryBuilder.must(QueryBuilders.matchQuery("storeId", storeId));
            searchSourceBuilder.query(queryBuilder);
        }

        search.source(searchSourceBuilder);

        try{
            SearchResponse searchResponse = restHighLevelClient.search(search, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            Max maxPrice = aggregations.get("maxPrice");
            if(maxPrice != null && !maxPrice.getValueAsString().equals("-Infinity")){
                return Math.ceil(maxPrice.getValue());
            }else{
                return 0D;
            }
        }catch (Exception e){
            return 0D;
        }
    }

    /**
     * 查询归属地市
     * @param memberId  会员id
     * @return
     */
    @Override
    public List<ProvinceResponse> getArea(Long shopId, Long memberId) {
        // 查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        // 拼接会员搜索
        if(memberId != null && memberId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("memberId", memberId));
        }
        // 按商城环境
        if(shopId != null && shopId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("commodityShopList.shopId", shopId));
        }
        return this.queryEsArea(queryBuilder);
    }

    /**
     * 查询es中商品数据对应的区域信息
     * @param queryBuilder 查询条件
     */
    @Override
    public List<ProvinceResponse> queryEsArea(BoolQueryBuilder queryBuilder){
        //构建查询条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().trackTotalHits(true);
        SearchRequest search = new SearchRequest(Constants.ES_COMMODITY_INDEX);
        searchSourceBuilder.size(0);
        searchSourceBuilder.query(queryBuilder);
        //分组
        TermsAggregationBuilder aggregationBrandId = AggregationBuilders.terms("group_provinceCode").field("commodityAreaList.provinceCode.keyword").size(1200000)
                .subAggregation(AggregationBuilders.terms("group_cityCode").field("commodityAreaList.cityCode.keyword").subAggregation(AggregationBuilders.terms("group_regionCode").field("commodityAreaList.regionCode.keyword")));
        searchSourceBuilder.aggregation(aggregationBrandId);
        search.source(searchSourceBuilder);
        //搜索
        try{
            HashMap<String, ProvinceResponse> provinceMap = new HashMap<>();
            HashMap<String, CityResponse> cityMap = new HashMap<>();
            SearchResponse searchResponse = restHighLevelClient.search(search, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            if(aggregations != null){
                Terms provinceCodeTerms = aggregations.get("group_provinceCode");
                List<? extends Terms.Bucket> provinceBuckets = provinceCodeTerms.getBuckets();
                if(provinceBuckets != null){
                    //获取redis中行政区域信息
                    Map<String, String> areaMap = redisStringUtils.hGetAll(Constants.REDIS_KEY_AREA, Constants.REDIS_PLATFORM_MANAGE_INDEX);

                    provinceBuckets.forEach(provinceCodeBucket -> {
                        ProvinceResponse province;
                        String provinceCode = String.valueOf(provinceCodeBucket.getKey());
                        if (StringUtils.isNotEmpty(provinceCode)) {
                            if(provinceMap.get(provinceCode) != null){
                                province = provinceMap.get(provinceCode);
                            }else{
                                //省份信息
                                province = new ProvinceResponse();
                                province.setProvinceCode(provinceCode);
                                String area = areaMap.get(provinceCode);
                                JSONObject jsonObject = JSONUtil.parseObj(area);
                                String provinceName = jsonObject.getStr("name");
                                province.setProvinceName(provinceName);
                                province.setTitle(PinyinUtils.getFirstChar(provinceName));
                            }
                            Terms cityCodeTerms = provinceCodeBucket.getAggregations().get("group_cityCode");
                            List<? extends Terms.Bucket> cityCodeBuckets = cityCodeTerms.getBuckets();
                            if(cityCodeBuckets != null){
                                cityCodeBuckets.forEach(cityCodeBucket -> {
                                    CityResponse city;
                                    String cityCode = String.valueOf(cityCodeBucket.getKey());
                                    if (StringUtils.isNotEmpty(cityCode)) {
                                        if(cityMap.get(cityCode) != null){
                                            city = cityMap.get(cityCode);
                                        }else{
                                            //城市信息
                                            city = new CityResponse();
                                            city.setCityCode(cityCode);
                                            String area = areaMap.get(cityCode);
                                            JSONObject jsonObject = JSONUtil.parseObj(area);
                                            String cityName = jsonObject.getStr("name");
                                            String pcode = jsonObject.getStr("pcode");
                                            city.setCityName(cityName);
                                            city.setTitle(PinyinUtils.getFirstChar(cityName));
                                            //省份对应的城市
                                            List<CityResponse> cityList = province.getCityList() == null ? new ArrayList<>() : province.getCityList();
                                            if(!cityList.contains(city) && provinceCode.equals(pcode)){
                                                cityList.add(city);
                                                province.setCityList(cityList.stream().sorted(Comparator.comparing(CityResponse::getTitle)).collect(Collectors.toList()));
                                            }
                                        }
                                        Terms regionCodeTerms = cityCodeBucket.getAggregations().get("group_regionCode");
                                        List<? extends Terms.Bucket> regionCodeBuckets = regionCodeTerms.getBuckets();
                                        if(regionCodeBuckets != null){
                                            regionCodeBuckets.forEach(regionCodeBucket -> {
                                                String regionCode = String.valueOf(regionCodeBucket.getKey());
                                                if (StringUtils.isNotEmpty(regionCode)) {
                                                    //区域信息
                                                    RegionResponse region = new RegionResponse();
                                                    region.setRegionCode(regionCode);
                                                    String area = areaMap.get(regionCode);
                                                    JSONObject jsonObject = JSONUtil.parseObj(area);
                                                    String regionName = jsonObject.getStr("name");
                                                    String pcode = jsonObject.getStr("pcode");
                                                    region.setRegionName(regionName);
                                                    region.setTitle(PinyinUtils.getFirstChar(regionName));
                                                    //城市对应的区域
                                                    List<RegionResponse> regionList = city.getRegionList() == null ? new ArrayList<>() : city.getRegionList();
                                                    if(!regionList.contains(region) && cityCode.equals(pcode)){
                                                        regionList.add(region);
                                                        city.setRegionList(regionList.stream().sorted(Comparator.comparing(RegionResponse::getTitle)).collect(Collectors.toList()));
                                                    }
                                                }
                                            });
                                        }
                                        cityMap.put(cityCode, city);
                                    }
                                });
                            }
                            provinceMap.put(provinceCode, province);
                        }
                    });
                }
            }
            return new ArrayList<>(provinceMap.values());
        }catch (Exception e){
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    /**
     * 商品搜索自动补全
     * @param shopId            商城id
     * @param channelShopId     渠道商城id
     * @param name 商品名称
     * @return
     */
    @Override
    public List<String> getCommodityCompletion(Long shopId, Long channelShopId, String name) {
        return new ArrayList<>();
//        try{
//            String commodityNameSuggest = "commodity_name_suggest";
//            Request request = new Request("GET", Constants.ES_COMMODITY_INDEX + "/_search");
//            String format = "{" +
//                        "  \"_source\": false, " +
//                        "  \"suggest\": {" +
//                        "    \"%s\": {" +
//                        "      \"prefix\": \"%s\"," +
//                        "      \"completion\":{" +
//                        "        \"field\":\"tagsName\"," +
//                        "        \"size\": 10," +
//                        "        \"skip_duplicates\":true," +
//                        "        \"contexts\": {\n" +
//                        "           \"shopId_tab\": [" + shopId + "]\n" +
//                        "        }" +
//                        "      }" +
//                        "    }" +
//                        "  }" +
//                        "}";
//            request.setJsonEntity(String.format(format, commodityNameSuggest, name));
//            Response response = restHighLevelClient.getLowLevelClient().performRequest(request);
//            String entity = EntityUtils.toString(response.getEntity());
//            JSONArray suggest = JSONUtil.parseObj(entity).getJSONObject("suggest").getJSONArray(commodityNameSuggest);
//            JSONArray options = suggest.getJSONObject(0).getJSONArray("options");
//
//            List<String> resultList = new ArrayList<>();
//            for(int i = 0; i < options.size(); i ++){
//                JSONObject json = options.getJSONObject(i);
//                resultList.add(json.getStr("text"));
//            }
//            return resultList;
//        }catch (Exception e){
//            e.printStackTrace();
//            return new ArrayList<>();
//        }
    }

    /**
     * 查询商品是否上架
     * @param commodityId
     * @return
     */
    @Override
    public Boolean getCommodityIsPublish(Long commodityId, Integer type, Long channelMemberId, Long memberId) {
        Commodity commodity = commodityRepository.findById(commodityId).orElse(null);
        if(commodity != null){
            if(ShopTypeEnum.ENTERPRISE.getCode().equals(type) || ShopTypeEnum.SCORE.getCode().equals(type)){
                List<CommodityShop> commodityShopList = commodity.getCommodityShopList().stream().filter(commodityShop -> commodityShop.getType().equals(type)).collect(Collectors.toList());
                return !commodityShopList.isEmpty();
            }else{
                List<ChannelCommodityMember> channelCommodityMemberList = commodity.getMemberList().stream().filter(channelCommodityMember -> channelCommodityMember.getChannelMemberId().longValue() == channelMemberId.longValue() && (channelCommodityMember.getMemberId().longValue() == memberId.longValue() || channelCommodityMember.getMemberId() == 0)).collect(Collectors.toList());
                return !channelCommodityMemberList.isEmpty();
            }
        }else{
            return false;
        }
    }

    /**################################################  APP  ##############################################################**/

    @Override
    public List<SimpleNameUrlResponse> getFirstCategory(Long shopId, Long memberId) {
        Set<Long> categoryIdList = new HashSet<>();
        // 查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        //定义参数变量
        String esField;
        String redisKey;
        if(memberId != null && memberId > 0){
            esField = "customerCategory.fullId.keyword";
            redisKey = Constants.REDIS_KEY_CUSTOMER_CATEGORY;

            // 拼接会员id搜索
            queryBuilder.must(QueryBuilders.matchQuery("memberId", memberId));
        }else{
            esField = "customerCategory.category.fullId.keyword";
            redisKey = Constants.REDIS_KEY_CATEGORY;
        }

        // 按商城环境
        if(shopId != null && shopId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("commodityShopList.shopId", shopId));
        }

        //构建查询条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().trackTotalHits(true);
        SearchRequest search = new SearchRequest(Constants.ES_COMMODITY_INDEX);
        searchSourceBuilder.size(0);
        searchSourceBuilder.query(queryBuilder);
        //分组
        TermsAggregationBuilder aggregationCategoryId = AggregationBuilders.terms("group_categoryId").field(esField).size(1200000);
        searchSourceBuilder.aggregation(aggregationCategoryId);
        search.source(searchSourceBuilder);
        try{
            //搜索
            SearchResponse searchResponse = restHighLevelClient.search(search, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            if(aggregations != null){
                Terms brandTerms = aggregations.get("group_categoryId");
                List<? extends Terms.Bucket> brandBuckets = brandTerms.getBuckets();
                if(brandBuckets != null){
                    brandBuckets.forEach(bucket -> {
                        //将品类进行组装
                        String categoryFullId = String.valueOf(bucket.getKey());
                        categoryIdList.add(Long.valueOf(categoryFullId.split(Constants.TRANSFER_STR + Constants.SPLIT_STR_FULL_ID)[0]));
                    });
                }
            }
            if(categoryIdList.size() > 0){
                Map<String, String> categoryMap = redisStringUtils.hGetAll(redisKey, Constants.REDIS_PRODUCT_INDEX);
                return categoryIdList.stream().map(categoryId -> {
                    String category = categoryMap.get(String.valueOf(categoryId));
                    JSONObject jsonObject = JSONUtil.parseObj(category);
                    SimpleNameUrlResponse categoryResponse = new SimpleNameUrlResponse();
                    categoryResponse.setId(categoryId);
                    categoryResponse.setName(jsonObject.getStr("name"));
                    categoryResponse.setImageUrl(jsonObject.getStr("imageUrl"));
                    return categoryResponse;
                }).collect(Collectors.toList());
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return new ArrayList<>();
    }

    /**
     * 根据品牌id查询品类下的品牌
     * @returnPOST
     */
    @Override
    public List<CategoryBrandResponse> getCategoryByBrand(List<Long> brandIdList, Long shopId) {
        List<Commodity> commodityList = commodityRepository.findByBrandIdInAndCommodityShopListShopId(brandIdList, shopId);
        if(commodityList != null && !commodityList.isEmpty()){
            HashMap<Long, CategoryBrandResponse> map = new HashMap<>();
            commodityList.forEach(commodity -> {
                Brand brand = commodity.getBrand();
                CustomerCategory customerCategory = commodity.getCustomerCategory();
                if(customerCategory != null){
                    Category category = customerCategory.getCategory();
                    if(category != null){
                        Long categoryId = category.getId();
                        String name = category.getName();
                        String imageUrl = category.getImageUrl();
                        CategoryBrandResponse categoryBrandResponse = map.get(categoryId);
                        Set<BrandResponse> brandResponseList = new HashSet<>();
                        if(categoryBrandResponse != null){
                            brandResponseList = categoryBrandResponse.getBrandResponseList();
                            if(brandResponseList == null || brandResponseList.isEmpty()){
                                brandResponseList = new HashSet<>();
                            }
                        }else{
                            categoryBrandResponse = new CategoryBrandResponse();
                            categoryBrandResponse.setId(categoryId);
                            categoryBrandResponse.setName(name);
                            categoryBrandResponse.setImageUrl(imageUrl);
                        }
                        brandResponseList.add(BeanUtil.copyProperties(brand, BrandResponse.class));
                        categoryBrandResponse.setBrandResponseList(brandResponseList);
                        map.put(categoryId, categoryBrandResponse);
                    }
                }
            });
            if(map.size() > 0){
                return new ArrayList<>(map.values());
            }
        }
        return new ArrayList<>();
    }

    /**
     * 根据商品id查询品类下的商品
     * @return
     */
    @Override
    public List<CategoryCommodityResponse> getCategoryByCommodityId(List<Long> commodityIdList) {
        List<Commodity> commodityList = commodityRepository.findByIdIn(commodityIdList);
        HashMap<Long, CategoryCommodityResponse> map = new HashMap<>();
        commodityList.forEach(commodity -> {
            CustomerCategory customerCategory = commodity.getCustomerCategory();
            if(customerCategory != null){
                Category category = customerCategory.getCategory();
                if(category != null){
                    Long categoryId = category.getId();
                    String name = category.getName();
                    String imageUrl = category.getImageUrl();
                    CategoryCommodityResponse categoryCommodityResponse = map.get(categoryId);
                    Set<CommoditySearchResponse> commodityResponseList = new HashSet<>();
                    if(categoryCommodityResponse != null){
                        commodityResponseList = categoryCommodityResponse.getCommodityResponseList();
                        if(commodityResponseList == null || commodityResponseList.isEmpty()){
                            commodityResponseList = new HashSet<>();
                        }
                    }else{
                        categoryCommodityResponse = new CategoryCommodityResponse();
                        categoryCommodityResponse.setId(categoryId);
                        categoryCommodityResponse.setName(name);
                        categoryCommodityResponse.setImageUrl(imageUrl);
                    }
                    commodityResponseList.add(BeanUtil.copyProperties(commodity, CommoditySearchResponse.class));
                    categoryCommodityResponse.setCommodityResponseList(commodityResponseList);
                    map.put(categoryId, categoryCommodityResponse);
                }
            }
        });
        return new ArrayList<>(map.values());
    }

    /**
     * 根据一级品类查询品牌(平台后台品类)
     * @param categoryId 一级品类id
     * @returnPOST
     */
    @Override
    public Set<BrandResponse> getBrandByFirstCategory(Long categoryId, Long shopId) {
        List<Commodity> commodityList = commodityRepository.findByCustomerCategoryCategoryFullIdStartingWithAndCommodityShopListShopId(String.format(Constants.CATEGORY_FULL_ID_NUM, categoryId), shopId);
        return commodityList.stream().map(commodity -> {
            Brand brand = commodity.getBrand();
            if (brand != null) {
                return BeanUtil.copyProperties(brand, BrandResponse.class);
            } else {
                return null;
            }
        }).filter(Objects::nonNull).collect(Collectors.toSet());
    }

    /**
     * 根据一级品类查询品牌(会员品类)
     * @param customerCategoryId 一级品类id
     * @returnPOST
     */
    @Override
    public Set<BrandResponse> getBrandByFirstCustomerCategory(Long customerCategoryId, Long shopId) {
        List<Commodity> commodityList = commodityRepository.findByCustomerCategoryFullIdStartingWithAndCommodityShopListShopId(String.format(Constants.CATEGORY_FULL_ID_NUM, customerCategoryId), shopId);
        return commodityList.stream().map(commodity -> {
            Brand brand = commodity.getBrand();
            if (brand != null) {
                return BeanUtil.copyProperties(brand, BrandResponse.class);
            } else {
                return null;
            }
        }).filter(Objects::nonNull).collect(Collectors.toSet());
    }

    /**
     * 保存分享码
     * @param shareCodeRequest
     * @return
     */
    @Override
    public Boolean saveShareCode(ShareCodeRequest shareCodeRequest) {
        String code = shareCodeRequest.getCode();
        String value = shareCodeRequest.getValue();
        //过期时间十分钟
        long expire = 10 * 60;
        return redisStringUtils.set(code, value, expire, Constants.REDIS_PRODUCT_INDEX);
    }

    /**
     * 查询分享码
     * @param code
     * @return
     */
    @Override
    public String getShareCode(String code) {
        return redisStringUtils.get(code, Constants.REDIS_PRODUCT_INDEX);
    }

    /**
     * 通过商品skuId查询商品库存
     * @param shopId            商城id
     * @param memberId          会员id
     * @param commoditySkuId    商品skuId
     */
    @Override
    public double getCommodityStockBySkuId(Long shopId, Long memberId, Long commoditySkuId) {
        //获取库存数据
        String key = CommonConstant.FREIGHT_SPACE_REDIS_KEY + shopId + "_" + commoditySkuId;
        String[] fields = new String[]{String.valueOf(memberId), CommonConstant.FREIGHT_All};
        List<String> stockList = redisStringUtils.hMGet(key, fields, Constants.REDIS_PRODUCT_INDEX);
        return stockList.stream().filter(Objects::nonNull).map(Double::parseDouble).reduce(Double::sum).orElse(0.0);
    }

    /**
     * 查询商品sku信息
     * @param commoditySearchRequest 请求参数
     */
    @Override
    public List<CommoditySkuResponse> getCommoditySkuList(CommoditySearchRequest commoditySearchRequest) {
        Long shopId = commoditySearchRequest.getShopId();
        Long loginMemberId = commoditySearchRequest.getLoginMemberId();
        Long loginMemberRoleId = commoditySearchRequest.getLoginMemberRoleId();
        List<Long> skuIdInList = commoditySearchRequest.getSkuIdInList();
        //查询商品信息
        List<Commodity> commodityList = this.getEsCommodityList(commoditySearchRequest);
        if(!CollectionUtils.isEmpty(commodityList)){
            //查询登录用户的所有上级对应的会员等级
            Map<String, Integer> memberLevelMap = this.getMemberLevel(loginMemberId, loginMemberRoleId);
            List<CommoditySkuResponse> commoditySkuResponseList = new ArrayList<>();
            commodityList.forEach(commodity -> {
                //查询当前登录用户在对应供应商下的等级
                Integer loginMemberLevel = memberLevelMap.get(commodity.getMemberId() + Constants.UNDERLINE_STR + commodity.getMemberRoleId());
                //根据价格策略设置价格
                this.setCommodityPrice(commodity, shopId, loginMemberId, loginMemberRoleId, loginMemberLevel == null ? 0 : loginMemberLevel);

                //不同商城显示不同的已售数量
                AtomicReference<Double> sold = new AtomicReference<>((double) 0);
                List<CommoditySoldCount> commoditySoldCountList = commodity.getCommoditySoldCountList();
                if(commoditySoldCountList != null && commoditySoldCountList.size() > 0){
                    commoditySoldCountList.forEach(commoditySoldCount -> {
                        Long commoditySoldCountShopId = commoditySoldCount.getShopId();
                        if(commoditySoldCountShopId.equals(shopId)){
                            sold.set(commoditySoldCount.getSold());
                        }
                    });
                }

                //获取sku信息
                List<CommodityUnitPricePic> unitPricePicList = commodity.getUnitPricePicList();
                List<CommoditySkuResponse> list = unitPricePicList.stream().map(commodityUnitPricePic -> {
                    Long skuId = commodityUnitPricePic.getId();
                    //如果通过skuId查询，则过滤掉不在查询范围的数据
                    if(!CollectionUtils.isEmpty(skuIdInList) && !skuIdInList.contains(skuId)){return null;}
                    CommoditySkuResponse commoditySkuResponse = BeanUtil.copyProperties(commodity, CommoditySkuResponse.class);
                    commoditySkuResponse.setId(skuId);
                    commoditySkuResponse.setCommodityId(commodity.getId());
                    commoditySkuResponse.setSold(sold.get());
                    //商品属性
                    List<GoodsAttribute> attributeAndValueList = commodityUnitPricePic.getAttributeAndValueList();
                    String attribute = StringUtils.join(attributeAndValueList.stream().sorted(Comparator.comparing(GoodsAttribute::getId).reversed()).map(commodityGoodsAttribute -> commodityGoodsAttribute.getCustomerAttributeValue().getValue()).toArray(String[]::new), Constants.COMMODITY_NAME_SPLIT_STR);
                    if (StringUtils.isNotEmpty(attribute)) {
                        commoditySkuResponse.setName(commodity.getName() + Constants.COMMODITY_NAME_SPLIT_STR + attribute);
                    } else {
                        commoditySkuResponse.setName(commodity.getName());
                    }
                    return commoditySkuResponse;
                }).filter(Objects::nonNull).collect(Collectors.toList());
                commoditySkuResponseList.addAll(list);
            });
            return commoditySkuResponseList;
        }
        return null;
    }

}